﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using Grundy.Common;
using Grundy.Message;

namespace Grundy.CryptographicServices
{
    public class NodeFingerprintIdentityProvider : IdentityProvider
    {
        public bool IgnoreMacAddresses { get; set; }

        private IdentifierCollection _machineIdentifiers = GetMachineIdentifiers();

        public override IdentifierCollection GetIdentifiers()
        {
            var identifiers = new IdentifierCollection(_machineIdentifiers);
            identifiers.ForEachItemDo(i =>
                                            {
                                                if (i is MacAddressIdentifier)
                                                {
                                                    i.Ignore = IgnoreMacAddresses;
                                                }
                                            });

            return identifiers;
        }

        private static IdentifierCollection GetMachineIdentifiers()
        {
            var mapping = new Identifiers();
            IEnumerable<Identifier> processorIdentifiers = GetIdentifiersInternal("Win32_Processor", mapping.IdentifierNameToW32NameMapping[Identifiers.Processor])
                .Select(i => new ProcessorIdentifier{Value = i.Item2, Ignore = false});
            IEnumerable<Identifier> biosIdentifiers = GetIdentifiersInternal("Win32_BIOS", mapping.IdentifierNameToW32NameMapping[Identifiers.Bios])
                .Select(i => new BiosIdentifier{ Value = i.Item2, Ignore = false });
            IEnumerable<Identifier> macIdentifiers = GetIdentifiersInternal("Win32_NetworkAdapterConfiguration", mapping.IdentifierNameToW32NameMapping[Identifiers.MacAddress])
                .Select(i => new MacAddressIdentifier{Value = i.Item2 });
            return new IdentifierCollection(processorIdentifiers.Concat(biosIdentifiers.Concat(macIdentifiers)));
        }

        protected static List<Tuple<string, string>> GetIdentifiersInternal(string container, string attribute)
        {
            return new ManagementObjectSearcher(string.Format("select * from {0}", container)).Get().OfType<ManagementObject>()
                .SelectMany(mo => mo.Properties.OfType<PropertyData>()).Where(p => p.Name.EqualsIgnoreCase(attribute))
                .Where(p => p.Value != null)
                .Select(p => Tuple.Create(p.Name, p.Value.ToString()))
                .ToList();
        }

        public override string Type
        {
            get { return "NodeFingerprintIdentityProvider"; }
        }
    }
}